<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/ajax.js"></script>
</head>

<body>

</body>
<script>
    // Promise封装的异步操作 => 调用此方法会立即返回Promise实例(进行中) => 指定时间之后变为成功或失败的状态
    function getNumAsync(num = 0, delay = 0, isFulfilled = true) {
        var p = new Promise(function (resolve, reject) { // 形参
            setTimeout(function () {
                isFulfilled ? resolve(num) : reject(num);
            }, delay)
        });
        return p;  // 返回Promise对象  {<pending>:undefined}
    }


    // 2. 同时调用三个函数 => 三个Promise实例 
    // T1
    // T2   => 按最慢的来(3s)
    // T3
    // var p1 = getNumAsync(2, 2000); // 返回Promise实例  2s后 =>{<fulfilled>:1}
    // var p2 = getNumAsync(1, 1000); // 返回Promise实例  1s后 =>{<fulfilled>:1}
    // var p3 = getNumAsync(3, 3000); // 返回Promise实例  3s后 =>{<fulfilled>:1}

    // p1.then(function (arg) {
    //     console.log("fulfilled", arg);
    //     return p2;  // 返回Promise实例
    // }).then(function (arg) {
    //     console.log("fulfilled", arg);
    //     return p3;  // 返回Promise实例
    // }).then(function (arg) {
    //     console.log("fulfilled", arg);
    // }).catch(function (err) {
    //     console.log("rejected", err);
    // })

    // 多请求并行
    // all
    // (1)同时接收多个Promise实例(异步操作),返回一个新的Promise实例,全都成功,新的Promise实例也成功,就把每一个Promise实例的结果按顺序整合到数组中,作为新的Promise实例存储的数据,有一个失败,新的Promise实例也失败

    // 模拟封装all   => 特征 全都成功才成功,有一个失败就停止 (按最慢的)
    /* function all(list) {  // [p1, p2, p3]
        return new Promise(function (resolve, reject) {
            let arr = [];
            let count = 0; //计数
            for (let i = 0; i < list.length; i++) {
                let p = list[i];// 每一个Promise实例
                // 指定状态改变时要执行的回调函数(异步操作)
                p.then(data => {
                    // arr.push(data); //成功一个就放一个(谁先有结果 谁先放到arr中)
                    arr[i] = data; //对应下标赋值
                    count++;
                    if (count == list.length) {
                        // 返回数组
                        resolve(arr);
                    }
                }).catch(err => {
                    //返回错误
                    reject(err);
                })
            }
        })
    }

    var p1 = getNumAsync(1, 2000); // 返回Promise实例  2s后 =>{<fulfilled>:1}
    var p2 = getNumAsync(2, 1000); // 返回Promise实例  1s后 =>{<fulfilled>:1}
    var p3 = getNumAsync(3, 3000); // 返回Promise实例  3s后 =>{<fulfilled>:1}

    var p = all([p1, p2, p3]);

    p.then(list => {
        console.log("fulfilled", list);
    }).catch(err => {
        console.log("rejected", err);
    }) */


    // allSettled 无论成功还是失败 都不影响后续的执行  => 返回最终的结果(数组 包含成功/失败)
    // (1)同时接收多个Promise实例(异步操作),返回一个新的Promise实例,无论成功还是失败 都不影响后续的执行  => 返回最终的结果(数组)
    // [
    //     { status: 'fulfilled', value: 1 },
    //     { status: 'rejected', reason: 2 },
    //     { status: 'fulfilled', value: 3 },
    // ]
    /* function allSettled(list) {  // [p1, p2, p3]
        return new Promise(function (resolve, reject) {
            let arr = [];
            let count = 0; //计数
            for (let i = 0; i < list.length; i++) {
                let p = list[i];// 每一个Promise实例
                // 指定状态改变时要执行的回调函数(异步操作)
                p.then(data => {
                    // arr.push(data); //成功一个就放一个(谁先有结果 谁先放到arr中)
                    // arr[i] = data; //对应下标赋值
                    var o = { status: "fulfilled", value: data }
                    arr[i] = o;

                }).catch(err => {
                    //返回错误
                    // arr[i] = err; //对应下标赋值
                    var o = { status: "rejected", reason: err }
                    arr[i] = o;
                }).finally(function () {
                    count++;
                    if (count == list.length) {
                        // 返回数组
                        resolve(arr);
                    }
                })
            }
        })
    }

    var p1 = getNumAsync(1, 2000); // 返回Promise实例  2s后 =>{<fulfilled>:1}
    var p2 = getNumAsync(2, 1000, false); // 返回Promise实例  1s后 =>{<fulfilled>:1}
    var p3 = getNumAsync(3, 3000); // 返回Promise实例  3s后 =>{<fulfilled>:1}

    var p = allSettled([p1, p2, p3]);

    p.then(list => {
        console.log("fulfilled", list);
    }).catch(err => {
        console.log("rejected", err);
    }) */


    // race()   多请求并行时 获取最快的结果(无论成功还是失败)
    // (1)同时接收多个Promise实例(异步操作),返回一个新的Promise实例,新的Promise实例的状态和结果依赖于最先改变状态的Promise实例

    /* function race(list) {  // [p1, p2, p3]
        return new Promise(function (resolve, reject) {
            let arr = [];
            let count = 0; //计数
            for (let i = 0; i < list.length; i++) {
                let p = list[i];// 每一个Promise实例
                // 指定状态改变时要执行的回调函数(异步操作)
                p.then(data => {
                    resolve(data);
                }).catch(err => {
                    reject(err);
                })
            }
        })
    }

    var p1 = getNumAsync(1, 2000); // 返回Promise实例  2s后 =>{<fulfilled>:1}
    var p2 = getNumAsync(2, 1000, false); // 返回Promise实例  1s后 =>{<fulfilled>:1}
    var p3 = getNumAsync(3, 3000); // 返回Promise实例  3s后 =>{<fulfilled>:1}

    var p = race([p1, p2, p3]);

    p.then(arg => {
        console.log("fulfilled", arg);
    }).catch(err => {
        console.log("rejected", err);
    }) */


    // any()    接收多个Promise实例(异步操作)  有一个成功即可 => 全都成功走最快,全都失败报错
    // 同时接收多个Promise实例(异步操作),返回一个新的Promise实例,新的Promise实例的状态和结果依赖于最先改变状态的Promise实例
    function any(list) {  // [p1, p2, p3]
        return new Promise(function (resolve, reject) {
            let arr = [];
            let count = 0; //计数
            for (let i = 0; i < list.length; i++) {
                let p = list[i];// 每一个Promise实例
                // 指定状态改变时要执行的回调函数(异步操作)
                p.then(data => {
                    resolve(data);
                }).catch(err => {
                    count++;
                    if (count == list.length) { //全都失败
                        reject("全都失败");
                    }
                })
            }
        })
    }

    var p1 = getNumAsync(1, 2000, false); // 返回Promise实例  2s后 =>{<fulfilled>:1}
    var p2 = getNumAsync(2, 1000, false); // 返回Promise实例  1s后 =>{<fulfilled>:1}
    var p3 = getNumAsync(3, 3000, false); // 返回Promise实例  3s后 =>{<fulfilled>:1}

    var p = any([p1, p2, p3]);

    p.then(arg => {
        console.log("fulfilled", arg);
    }).catch(err => {
        console.log("rejected", err);
    }) 
</script>

</html>